﻿using System;
using System.Collections.Generic;
using System.Text;
using BCMS.Business.DataContract;
using BCMS.FrontEnd.DataContract;
using BCMS.Settings;
using System.Collections;

namespace BCMS.Business.Implementation
{
    public class DALclient
    {
        DataAccessClient client = new DataAccessClient();

        public DALclient()
        {

        }

        #region Coupons
        public int insertCoupon(string serial, DateTime start, DateTime expire, decimal parValue, int status, string note, int releaseId, int claimBy, bool isCanceled)
        {
            insertLog(new LogInfo(DateTime.Now,
                BCMS.Settings.GlobalVars.activeUser.ToString(),
                "Insert new coupon with serial = " + serial));
            return client.insertCoupon(serial, start, expire, parValue, status, note, releaseId, isCanceled);
        }

        public List<CouponUI> getCouponsByClaim(string username, string serial, DateTime from, DateTime to)
        {
            UserInfo user = client.getUserByName(username);
            Hashtable userList = getUserHastable();

            List<CouponUI> list = new List<CouponUI>();
            if (user != null)
            {
                List<CouponInfo> src = client.getCouponsByClaim(user.ID, serial, from, to);
                if (src != null)
                    foreach (CouponInfo item in src)
                    {
                        ReleaseInfo rls = client.getReleaseById(item.ReleaseId);
                        CouponUI tmp = new CouponUI(item, rls);
                        if (item.ClaimBy != null)
                            tmp.ClaimBy = ((UserUI)userList[item.ClaimBy]).UserName;

                        tmp.ClaimBy = ((UserUI)userList[item.ClaimBy]).UserName;
                        tmp.ReleaseDetail = rls.Detail;

                        list.Add(tmp);
                    }
                else return null;
            }
            else
                return null;

            return list;
        }
        public List<CouponUI> findClaimedCouponsBySeries(DateTime smaller, DateTime greater, string claimby)
        {
            UserInfo user = client.getUserByName(claimby);
            List<CouponInfo> src = client.findClaimedCouponsBySeries(smaller, greater, user.ID);
            if (src != null)
            {
                List<CouponUI> list = new List<CouponUI>();
                foreach (CouponInfo item in src)
                {
                    ReleaseInfo rls = client.getReleaseById(item.ReleaseId);
                    CouponUI tmp = new CouponUI(item, rls);
                    tmp.ClaimBy = claimby;
                    list.Add(tmp);
                }

                return list;
            }
            else
                return null;
        }

        public void batchClaim(List<string> serials, string username, string note, DateTime claimDate)
        {
            UserInfo user = client.getUserByName(username);
            if (user != null)
            {
                client.batchClaim(serials, user.ID, note, claimDate);
            }
            else
                throw new InvalidOperationException();

        }

        public void batchDelete(List<string> serials)
        {
            //delete coupons released
            foreach (string serial in serials)
            {
                CouponUI coupon = getCouponBySerial(serial);
                if (coupon != null)
                    deleteCouponBySerial(serial);
                client.updateReleaseQttyByName(Convert.ToInt64(1), coupon.ReleaseName);
            }
            this.insertLog(new LogInfo(DateTime.Now,
                BCMS.Settings.GlobalVars.activeUser.ToString(),
                string.Format("Deleted coupon in range {0} - {1}", serials[0], serials[serials.Count - 1])));
        }

        public void deleteCouponByReleaseId(int releaseId)
        {
            client.deleteCouponByReleaseId(releaseId);
            this.insertLog(new LogInfo(DateTime.Now,
                BCMS.Settings.GlobalVars.activeUser.ToString(),
                "Delete coupon by release with id = " + releaseId.ToString()));
        }

        public void deleteCouponBySerial(string serial)
        {
            client.deleteCouponBySerials(serial);
            this.insertLog(new LogInfo(DateTime.Now,
                BCMS.Settings.GlobalVars.activeUser.ToString(),
                "Delete coupon with serial = " + serial));
        }

        public CouponUI getCouponBySerial(string serial)
        {
            CouponInfo src = client.GetCouponBySerial(serial);
            Hashtable userList = getUserHastable();

            if (src != null)
            {
                ReleaseInfo rls = client.getReleaseById(src.ReleaseId);
                CouponUI tmp = new CouponUI(src, rls);
                if (src.ClaimBy != null)
                    tmp.ClaimBy = ((UserUI)userList[src.ClaimBy]).UserName;

                return tmp;
            }
            else
                return null;
        }

        public List<CouponInfo> searchCoupons(string serial, int status, DateTime t0)
        {
            List<CouponInfo> list = client.getCoupons(serial, status);

            if (list != null)
            {
                foreach (CouponInfo item in list)
                {
                    if (item.ExpireDate.CompareTo(t0) <= 0)
                        item.Note = "EXPIRED BY THE TIME SELECTED";
                    else if (item.ExpireDate.CompareTo(t0) >= 0)
                        item.Note = "GOOD";
                }
                return list;
            }
            else
                return null;
        }

        public void claimCouponBySerial(string serial, string userName, string note, DateTime claimDate)
        {
            UserInfo user = client.getUserByName(userName);
            client.claimCouponBySerial(serial, user.ID, note, claimDate);
            this.insertLog(new LogInfo(DateTime.Now, userName, "Claim coupon with serial = " + serial));
        }

        public void undoClaimCouponBySerial(string serial, string userName)
        {
            client.undoClaimCouponBySerial(serial);
            this.insertLog(new LogInfo(DateTime.Now, GlobalVars.activeUser, "UndoClaim coupon with serial = " + serial));
        }

        public void extendCouponBySerial(string serial, string note, DateTime expireDate)
        {
            client.extendCouponBySerial(serial, note, expireDate);
            this.insertLog(new LogInfo(DateTime.Now, GlobalVars.activeUser, "Extend coupon with serial = " + serial));
        }

        public void batchCouponExtend(List<string> serials, string note, DateTime expireDate)
        {
            client.batchCouponExtend(serials, note, expireDate);
        }

        public void undoClaimCouponBySerial(string serial)
        {
            CouponInfo cp = client.GetCouponBySerial(serial);
            ReleaseInfo rls = client.getReleaseById(cp.ReleaseId);

            client.extendCouponBySerial(serial, string.Empty, rls.ExpireDate);
            this.insertLog(new LogInfo(DateTime.Now, GlobalVars.activeUser, "UndoExtend coupon with serial = " + serial));
        }

        public void disposelCouponByReleaseId(int releaseId)
        {
            client.disposelCouponByReleaseId(releaseId, (int)CStatus.Disposed, (int)CStatus.Normal);
            this.insertLog(new LogInfo(DateTime.Now,
                BCMS.Settings.GlobalVars.activeUser.ToString(),
                "Cancel coupon by release with id = " + releaseId.ToString()));
        }

        public void cancelCouponBySerial(string serial)
        {
            client.cancelCouponBySerial(serial);
            this.insertLog(new LogInfo(DateTime.Now,
                BCMS.Settings.GlobalVars.activeUser.ToString(),
                "Cancel coupon by serial = " + serial));
        }

        public List<CouponUI> reportExpiredCouponDetail(DateTime fromDate, DateTime toDate, DateTime reportDate)
        {
            List<CouponInfo> src = client.reportExpiredCouponDetail(fromDate, toDate, reportDate);
            if (src != null)
            {
                List<CouponUI> list = new List<CouponUI>();
                foreach (CouponInfo item in src)
                {
                    ReleaseInfo rls = client.getReleaseById(item.ReleaseId);
                    CouponUI tmp = new CouponUI(item, rls);
                    list.Add(tmp);
                }

                return list;
            }
            else
                return null;
        }

        public List<CouponUI> reportUnexpiredUnclaimed(DateTime fromDate, DateTime toDate, DateTime reportDate)
        {
            List<CouponInfo> src = client.reportUnexpiredUnclaimed(fromDate, toDate, reportDate);
            if (src != null)
            {
                List<CouponUI> list = new List<CouponUI>();
                foreach (CouponInfo item in src)
                {
                    ReleaseInfo rls = client.getReleaseById(item.ReleaseId);
                    CouponUI tmp = new CouponUI(item, rls);
                    list.Add(tmp);
                }

                return list;
            }
            else
                return null;
        }

        public List<CouponBriefUI> reportClaimedCoupons(DateTime fromDate, DateTime toDate)
        {
            List<CouponBrief> src = client.reportClaimedCoupons(fromDate, toDate);
            Hashtable userList = getUserHastable();
            if (src != null)
            {
                List<CouponBriefUI> list = new List<CouponBriefUI>();
                foreach (CouponBrief item in src)
                {
                    CouponBriefUI tmp = new CouponBriefUI(item);
                    tmp.ClaimBy = ((UserUI)userList[item.ClaimBy]).UserName;

                    list.Add(tmp);
                }
                return list;
            }
            else
                return null;
        }

        public List<CouponBriefUI> reportClaimedCouponsByUser(string claimBy, DateTime fromDate, DateTime toDate)
        {
            UserInfo user = client.getUserByName(claimBy);
            List<CouponBrief> src = client.reportClaimedCouponsByUser(user.ID, fromDate, toDate);

            if (src != null)
            {
                List<CouponBriefUI> list = new List<CouponBriefUI>();
                foreach (CouponBrief item in src)
                    list.Add(new CouponBriefUI(item));

                return list;
            }
            else
                return null;
        }

        public List<CouponBriefUI> reportExpireCoupons(DateTime reportDate)
        {
            List<CouponBrief> src = client.reportExpireCoupons(reportDate);

            if (src != null)
            {
                List<CouponBriefUI> list = new List<CouponBriefUI>();
                foreach (CouponBrief item in src)
                    list.Add(new CouponBriefUI(item));

                return list;
            }
            else
                return null;
        }

        public List<CouponBriefUI> reportUnExpireCoupons(DateTime reportDate)
        {
            List<CouponBrief> src = client.reportUnExpireCoupons(reportDate);

            if (src != null)
            {
                List<CouponBriefUI> list = new List<CouponBriefUI>();
                foreach (CouponBrief item in src)
                    list.Add(new CouponBriefUI(item));

                return list;
            }
            else
                return null;
        }

        public List<CouponBriefUI> reportCouponsByReleaseDate(DateTime fromDate, DateTime toDate)
        {
            List<CouponBrief> src = client.reportCouponsByReleaseDate(fromDate, toDate);

            if (src != null)
            {
                List<CouponBriefUI> list = new List<CouponBriefUI>();
                foreach (CouponBrief item in src)
                    list.Add(new CouponBriefUI(item));

                return list;
            }
            else
                return null;
        }
        #endregion

        #region  Releases

        public ReleaseUI getReleaseByName(string name)
        {
            ReleaseInfo item = client.getReleaseByName(name);
            if (item != null)
                return new ReleaseUI(item);
            else
                return null;
        }

        public int insertRelease(string name, DateTime start, DateTime expire, long qtty, decimal parvalue, int target, string detail, string note, int kind, string rcode, long rlow, long rhigh)
        {
            int id = client.insertRelease(name, start, expire, qtty, parvalue, target, detail, note, kind, rcode, rlow, rhigh);
            if (id > 0)
                this.insertLog(new LogInfo(DateTime.Now,
                                BCMS.Settings.GlobalVars.activeUser.ToString(),
                                "Created new release with id: " + id.ToString()));

            return id;
        }

        public List<ReleaseUI> getReleaseByDate(DateTime from, DateTime to)
        {
            List<ReleaseInfo> src = client.getReleaseByDate(from, to);
            if (src != null)
            {
                List<ReleaseUI> list = new List<ReleaseUI>();
                foreach (ReleaseInfo item in src)
                    list.Add(new ReleaseUI(item));

                return list;
            }
            else
                return null;
        }

        public List<string> getDetailSuggest()
        {
            return client.getDetailSuggest();
        }

        public ReleaseUI getReleaseById(int releaseId)
        {
            ReleaseInfo src = client.getReleaseById(releaseId);
            if (src != null)
                return new ReleaseUI(src);
            else
                return null;
        }

        public void updateReleaseNote(int releaseId, string note)
        {
            client.updateReleaseNote(releaseId, note);
            this.insertLog(new LogInfo(DateTime.Now, GlobalVars.activeUser,
                "Update note of release with id = " + releaseId.ToString()));
        }

        public void updateReleaseStatusById(int releaseId, int newStatus, string note)
        {
            client.updateReleaseStatusById(releaseId, newStatus, note);
            this.insertLog(new LogInfo(DateTime.Now, GlobalVars.activeUser,
                "Update status of release with id = " + releaseId.ToString()));

        }

        public void updateReleaseById(int releaseId, string name, DateTime start, DateTime expire, long qtty, decimal parvalue, int target, string detail, string note, int kind, string rcode, long rlow, long rhigh)
        {
            client.updateReleaseById(releaseId, name, start, expire, qtty, parvalue, target, detail, note, kind, rcode, rlow, rhigh);
        }

        public void deleteReleaseById(int releaseId)
        {
            client.deleteRelease(releaseId);
            this.insertLog(new LogInfo(DateTime.Now, GlobalVars.activeUser,
                "Delete release with id = " + releaseId.ToString()));
        }

        public List<ReleaseInfo> getAllRelease()
        {
            return client.getAllRelease();
        }

        public List<ReleaseUI> searchRelease(string code, long num, long parValue, int kind, int target, string detail, DateTime from, DateTime to)
        {
            List<ReleaseInfo> src = client.searchRelease(code, num, parValue, kind, target, detail, from, to);
            if (src != null)
            {
                List<ReleaseUI> list = new List<ReleaseUI>();
                foreach (ReleaseInfo item in src)
                    list.Add(new ReleaseUI(item));

                return list;
            }
            else
                return null;
        }
        #endregion

        #region Log
        public void insertLog(LogInfo item)
        {
            client.insertLog(item);
        }

        public void clearLogBeforeDate(DateTime fromDate)
        {
            client.clearLogBeforeDate(fromDate);
        }

        public void clearLogByUserId(string userid)
        {
            client.clearLogByUserId(userid);
        }

        public List<LogUI> searchLog(string username, string action, DateTime fromDate, DateTime toDate)
        {
            List<LogInfo> src = client.searchLog(username, action, fromDate, toDate);
            if (src != null)
            {
                List<LogUI> list = new List<LogUI>();
                foreach (LogInfo item in src)
                    list.Add(new LogUI(item));

                return list;
            }
            else
                return null;
        }

        #endregion

        #region Users
        public Hashtable getUserHastable()
        {
            List<UserInfo> src = client.getAllUsers();
            Hashtable list = new Hashtable();
            foreach (UserInfo item in src)
                list.Add(item.ID, new UserUI(item));

            return list;
        }

        public UserUI UserLogin(string name, string password)
        {
            UserInfo src = client.UserLogin(name, password);
            if (src != null)
                return new UserUI(src);
            else
                return null;
        }

        public UserUI getUserByUserName(string userName)
        {
            UserInfo src = client.getUserByName(userName);
            if (src != null)
                return new UserUI(src);
            else
                return null;
        }

        public UserUI getUserById(int userId)
        {
            UserInfo src = client.getUserById(userId);
            if (src != null)
                return new UserUI(src);
            else
                return null;
        }

        public List<UserUI> getAllUsers()
        {
            List<UserInfo> src = client.getAllUsers();
            List<UserUI> list = new List<UserUI>();
            if (src != null)
            {
                foreach (UserInfo item in src)
                    list.Add(new UserUI(item));
                return list;
            }
            else
                return null;
        }

        public void changePassword(int usrId, string newPass)
        {
            client.ChangePassword(usrId, newPass);
            this.insertLog(new LogInfo(DateTime.Now,
                BCMS.Settings.GlobalVars.activeUser.ToString(),
                "Change password of user with id = " + usrId.ToString()));
        }

        public int insertUser(string username, string password, string roles, string fullname, string email, string phone, string address, string position, string department)
        {
            int userId = client.insertUser(username, password, roles, fullname, email, phone, address, position, department);
            if (userId > 0)
                this.insertLog(new LogInfo(DateTime.Now,
                GlobalVars.activeUser.ToString(), "Insert new user with id = " + userId.ToString()));
            return userId;

        }

        public UserInfo getUserInfo(int uID)
        {
            return client.getUserById(uID);
        }

        public void updateUser(int userId, string fullname, string email, string phone, string address, string position, string department)
        {
            client.updateUser(userId, fullname, email, phone, address, position, department);
            this.insertLog(new LogInfo(DateTime.Now,
                GlobalVars.activeUser.ToString(), "Update user information with id = " + userId.ToString()));
        }

        public void updateUserRoles(int uID, string roles)
        {
            client.updateUserRoles(uID, roles);
            this.insertLog(new LogInfo(DateTime.Now,
               BCMS.Settings.GlobalVars.activeUser.ToString(),
               "update roles of user with id = " + uID.ToString()));
        }
        #endregion

        public void importCoupons(ReleaseInfo rls, List<CouponInfo> coupons)
        {
            try
            {
                client.importCoupons(rls, coupons);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void ImportClaimCoupons(List<CouponInfo> coupons)
        {
            try
            {
                client.ImportClaimCoupons(coupons);
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }
    }

    public static class StaticDAL
    {
        public static void InsertNewCoupon(CouponInfo item)
        {
            DataAccessClient client = new DataAccessClient();
            client.insertCoupon(item.Serial, item.StartDate, item.ExpireDate, item.ParValue, item.Status, item.Note, item.ReleaseId, item.IsCanceled);
        }
    }
}
